Nashville PBS Design System · Audit · October 23, 2026
A full read of the design system against the original PBS Style Guide v3, On-Air Toolkit v3.1, station slates, and the session screenshots in uploads/. Scope note: I can only see this project's files, not other chats or Claude Code sessions, so the usage patterns below are inferred from what was uploaded and built here.
When another project binds this system, the sync ships only what the manifest lists: styles.css + tokens/*.css, the 14 font files, and _ds_bundle.js. The assets/ folder (logos, patterns, Symbol Crop) is not part of that contract. Every component and template that points at assets/… therefore 404s outside this project: Logo, PatternPanel, SymbolCrop (default assetPath), the Brand Cover and Strategic Report templates (hard-coded ../../assets/), and even the On-Air template's runtime base resolution, which correctly finds _ds/…/ but then finds no assets/ inside it.
Evidence: screenshot 9.46 PM ("the local _ds copy is missing assets/patterns and assets/brand — only fonts+tokens+bundle synced"), broken-image icon in the message slate (8.01 PM), alt-text "Nashville PBS" where the logo should be. Manifest keys: globalCssPaths, fonts[].files — no assets key.
Fix: make the logos and Symbol Crop code, not files. Each logo SVG is 5 KB; inline the four lockups into Logo.jsx (and the 1 KB Symbol Crop into SymbolCrop.jsx) so they travel inside the bundle, and switch the templates to <x-import … .Logo>. For the patterns, vectorize them: both are exact 12×12 grids of 160 px cells (quarter-circles, diagonals, solids in the three blues), so a pixel-faithful SVG is a few KB, crisp at UHD, and ships in the bundle. Fallback if you prefer the PNG pixels verbatim: embed them base64 in the bundle (+~290 KB).
CLAUDE.md holds the station's hard rules: title-safe 10%/action-safe 5%, UHD authoring, no Curve on air, 225° gradient for endpage/title card, lower-third spec, and the asset-portability rule. CLAUDE.md is project instructions for this project only. What travels to consuming projects is SKILL.md + readme.md, and those still say "all graphics 1920×1080" and "3.1 adds the Curve + hard Medium-Blue shadow" for on-air backgrounds, the exact treatment the station rejected. Rules get "ignored" because the agent never saw them, or saw the contradiction.
Fix: move every rule in CLAUDE.md into SKILL.md (short, imperative, with a "Broadcast hard rules" block) and reconcile readme.md. Keep CLAUDE.md as a pointer. Then encode the same rules in the templates so prose is a backup, not the enforcement.
Where the On-Air template constrains choices (accent enum, background enum, fixed title-safe insets) output has been correct. Where it relies on defaults and prose, it drifts: the slate styles default to the Community pattern plus a 55% navy overlay, but every real station slate in uploads/ (JIPNPBS24, SSNPBS24_N/T, support.png) uses Insight with no overlay. The readme states the opposite. Defaults are rules; make them match the station's actual output.
components/brand/Logo.jsx, PatternPanel.jsx, graphic/SymbolCrop.jsxDefault assetPath is relative to the host page ("assets/logos"), so it only works for a page sitting at the DS root; every card here already overrides it with ../../assets, and consumers have no copy at all. Inline the SVGs (logos, Symbol Crop) and vectorized patterns; drop assetPath from the props and .d.ts.
components/graphic/Curve.jsx + Curve.prompt.mdThe prompt never says "never on broadcast". The path M0,0 C36,5 84,42 100,100 is an approximation of the Profiles curve, which is why every render was rejected. Mark it print/digital only, pending the official vector from the PBS toolkit, and say so in the prompt and readme.
*.prompt.md examplesSeveral examples reference /assets/photos/… paths that do not exist (PillarDivider, RingAvatar, PullQuote, CurvedPhotoMask). Agents copy examples literally; use your-photo.jpg or an image-slot.
@startingPoint tagsDeprecated: consuming projects no longer offer starting points (templates replaced them). Remove the tags; promote the two or three that matter into templates (see §4).
tokens/fonts.css imports IBM Plex Mono from Google FontsAn external dependency in the one file every consumer loads. It is off-brand (PBS: a single typeface), and the cross-origin @import aborts font embedding in DOM-capture exports, which is why templates/on-air/ds-base.js carries a hack that deletes cross-origin rules. Remove the import; point --font-mono at a system mono stack.
--fw-semibold: 600 has no PBS Sans faceCuts are 300/400/500/700/800. Weight 600 gets synthesized or snapped differently per browser and exporter (the Express export file silently maps 600 to the Bold file). Remove the token or add a 600 @font-face that points at Bold so the result is deterministic.
--gradient-primary is 135° (light top-left). Broadcast endpage/title card need 225° (light top-right), so the template and the guideline card hand-roll it. Add --gradient-primary-tr and --gradient-primary-overlay-tr so consumers never improvise an angle.
--content-max: 1200px vs readme "1240px". Every template's ds-base.js loads the six token files and styles.css (which imports them again); standardize on ['styles.css'].
templates/on-air/OnAir.dc.htmlCorrect today: title-safe 192/108 px insets, 225° gradient on endpage/title card/promo, no Curve, lower-third bar at 6.5% / 20% with text inside title-safe, accent limited to Teal/Yellow/Coral/White, safe-guides overlay, runtime asset resolution, PBS Sans embedded for export.
Defects: (a) slate/support defaults should be Insight with overlay off (station reference), overlay as an opt-in for footage; (b) auto-fit floor is 24 px, unreadable on air — floor at ~40 px and allow a second line; (c) insets are px, so any frame-size change breaks them silently — use inset:10%; (d) UHD: the frame is 1920 CSS px, so masters come from a 2× capture, which is a clean 2:1 but should be stated in the template description and SKILL.md ("export at 2× for 3840×2160"); (e) pattern PNG is 1920² and gets upscaled at UHD — solved by vector patterns.
templates/strategic-report/StrategicReport.dc.htmlHard-coded ../../assets/ for the logo and both patterns (breaks in consumers). <script src="./doc-page.js"> and a <style id="__om-edit-overrides"> sit inside the template body instead of <helmet>. Patterns are used as stand-in photography inside CurvedPhotoMask, which the brand forbids (patterns never combine with imagery); use image-slot drop zones instead.
templates/brand-cover/BrandCover.dc.htmlHard-coded assetPath="../../assets/…" on both Logo and PatternPanel. Resolved automatically once the components carry their own assets.
templates/media-manager/MediaManager.dc.htmlNo external assets; renders from tokens and components only. This is the pattern the others should follow.
SKILL.mdSays "Read the README.md" (file is readme.md; case matters on some systems). Description lacks the trigger words that make a skill fire in Claude.ai and Claude Code ("WNPT", "on-air", "slate", "lower third", "endpage", "Media Manager", "PBS Blue"). No broadcast hard rules, no safe-area numbers, no "no Curve on air", still "all graphics 1920×1080". Needs a rewrite as the single authoritative brief (target under 150 lines, with the readme as the deep reference).
readme.mdContradicts the station: "slates use the Community pattern", "3.1 adds the Curve + hard shadow", "six styles" (there are seven), "1240px". Otherwise strong, and the color/typography sections match the Style Guide v3 extraction hex for hex.
guidelines/brand-logo.card.html + straysThe white lockups on this card point at two image-drop PNGs (nashvillepbs_logo_*-mrmr*.png) and a fill-less SVG also sits in guidelines/. Point the card back at assets/logos (or the inline Logo component) and delete the three strays.
tokens/colors.css match the Style Guide v3 text extraction (primary, secondary blues, accents, accent alts, secondary accents, neutrals).Safe_Areas guide, and the On-Air template honors it.From the uploads and templates: on-air promos and slates, donation end cards, the Media Manager spec sheet, the strategic plan, and brand covers. The two most common formats in any station's week have no artifact at all:
16:9 deck with title, section divider (pattern or gradient), agenda, text+image, stats, quote, closing/CTA slides. Rules baked in: PBS Sans only, one accent per slide, logo position, 24 px minimum type. Exports to PPTX/PDF.
Letter-size flowing document (memo, board report, one-pager) with repeating header/footer, cover option, callouts and pull quotes from the Editorial set. The Strategic Report is too specific to serve this.
1:1, 4:5, 9:16 and 16:9 frames with platform safe zones, tune-in line, logo lockup, pattern/gradient/photo backgrounds, one accent.
Print-ready Letter/Tabloid one-pager for events and screenings, CMYK-aware (Symbol Crop print artwork, pattern print values).
Send-ready header + section band using the pattern panels and pill CTAs.
Feature/lineup menu and a 3-line lower third variant, both listed in Toolkit 3.1 but not yet in the generator.
Rules reach Claude through exactly three channels. Each one has to carry the brand or the others will be undermined.
SKILL.md is already in Agent Skills format. Package it with readme.md, the rules, tokens, fonts and the logo SVGs, and have a Team admin provision it from the admin console so it is on by default for every member in Claude.ai, Cowork and Claude Code. Claude Team and Enterprise admins can provision skills centrally, and admin-provisioned skills are enabled by default for all users. The skill's description must name the triggers (Nashville PBS, WNPT, PBS Blue, on-air, slate, lower third, endpage, Media Manager, membership, pledge) so it fires without anyone invoking it..claude/skills/nashville-pbs-design/ and a short brand block to the repo's CLAUDE.md; for mandatory org-wide coverage IT can place skills in managed settings, which take highest priority.| Step | What | Outcome |
|---|---|---|
| 1 | Inline logos + Symbol Crop; vectorize patterns; drop assetPath; update Brand Cover, Strategic Report, cards | No more broken logos or patterns anywhere |
| 2 | Rewrite SKILL.md with the hard rules and triggers; reconcile readme; fix On-Air defaults (Insight, overlay off), fit floor, % insets, gradient tokens; remove Google import and weight 600 | Rules travel and templates match station output |
| 3 | Build Deck and Document templates (then Social) | Common work starts on-brand by default |
| 4 | Package the skill zip for org provisioning; hygiene (startingPoints, strays, prompt examples) | Team coverage without the DS pulled up |
Decisions I need from you are in the form that accompanies this report.